From c2bf763b7fdcb53ab63954975890aa786e8074cc Mon Sep 17 00:00:00 2001 From: "cl349@firebug.cl.cam.ac.uk" Date: Wed, 10 Aug 2005 09:46:51 +0000 Subject: [PATCH] Make xen daemon startup more robust. 1) make xenconsoled exit gracefully if xcs dies 2) daemonize xenstored before binding to xenstored socket 3) wait to close stdio in xenstored until we're ready to accept connections (so that PID=`xenstored --output-pid` doesn't return until it's ready to accept connections) 4) updates tools/misc/xend for these changes Signed-off-by: Anthony Liguori Signed-off-by: Rusty Russell Signed-off-by: Christian Limpach --- tools/console/daemon/io.c | 2 ++ tools/console/daemon/utils.c | 2 ++ tools/misc/xend | 4 +-- tools/xenstore/utils.c | 24 ------------- tools/xenstore/utils.h | 3 -- tools/xenstore/xenstored_core.c | 64 ++++++++++++++++++++++++++++----- 6 files changed, 62 insertions(+), 37 deletions(-) diff --git a/tools/console/daemon/io.c b/tools/console/daemon/io.c index 364245f019..87c3cc06e6 100644 --- a/tools/console/daemon/io.c +++ b/tools/console/daemon/io.c @@ -231,6 +231,7 @@ static void handle_tty_read(struct domain *dom) if (!write_sync(xcs_data_fd, &msg, sizeof(msg))) { dolog(LOG_ERR, "Write to xcs failed: %m"); + exit(1); } } else { close(dom->tty_fd); @@ -262,6 +263,7 @@ static void handle_xcs_msg(int fd) if (!read_sync(fd, &msg, sizeof(msg))) { dolog(LOG_ERR, "read from xcs failed! %m"); + exit(1); } else if (msg.type == XCS_REQUEST) { struct domain *dom; diff --git a/tools/console/daemon/utils.c b/tools/console/daemon/utils.c index 6bc7cfd3a5..96f823bdc7 100644 --- a/tools/console/daemon/utils.c +++ b/tools/console/daemon/utils.c @@ -59,6 +59,8 @@ bool _read_write_sync(int fd, void *data, size_t size, bool do_read) if (len < 1) { if (len == -1 && (errno == EAGAIN || errno == EINTR)) { + continue; + } else { return false; } } else { diff --git a/tools/misc/xend b/tools/misc/xend index 80a4f00ced..5abcdc6e04 100644 --- a/tools/misc/xend +++ b/tools/misc/xend @@ -24,6 +24,7 @@ import sys import socket import signal import time +import commands XCS_PATH = "/var/lib/xen/xcs_socket" XCS_EXEC = "/usr/sbin/xcs" @@ -116,8 +117,7 @@ def stop_xcs(): return def start_xenstored(): - if os.fork() == 0: - os.execvp('/usr/sbin/xenstored', ['/usr/sbin/xenstored']); + s,o = commands.getstatusoutput("/usr/sbin/xenstored --pid-file=/var/run/xenstore.pid"); def start_consoled(): if os.fork() == 0: diff --git a/tools/xenstore/utils.c b/tools/xenstore/utils.c index 0b1ac8aedd..2bc40e009b 100644 --- a/tools/xenstore/utils.c +++ b/tools/xenstore/utils.c @@ -80,30 +80,6 @@ void *malloc_nofail(size_t size) barf("malloc of %zu failed", size); } -/* Stevens. */ -void daemonize(void) -{ - pid_t pid; - - /* Separate from our parent via fork, so init inherits us. */ - if ((pid = fork()) < 0) - barf_perror("Failed to fork daemon"); - if (pid != 0) - exit(0); - - close(STDIN_FILENO); - close(STDOUT_FILENO); - close(STDERR_FILENO); - - /* Session leader so ^C doesn't whack us. */ - setsid(); - /* Move off any mount points we might be in. */ - chdir("/"); - /* Discard our parent's old-fashioned umask prejudices. */ - umask(0); -} - - /* This version adds one byte (for nul term) */ void *grab_file(const char *filename, unsigned long *size) { diff --git a/tools/xenstore/utils.h b/tools/xenstore/utils.h index a84f19a22a..5fbfceeaa9 100644 --- a/tools/xenstore/utils.h +++ b/tools/xenstore/utils.h @@ -40,9 +40,6 @@ void barf_perror(const char *fmt, ...) __attribute__((noreturn)); void *grab_file(const char *filename, unsigned long *size); void release_file(void *data, unsigned long size); -/* For writing daemons, based on Stevens. */ -void daemonize(void); - /* Signal handling: returns fd to listen on. */ int signal_to_fd(int signal); void close_signal(int fd); diff --git a/tools/xenstore/xenstored_core.c b/tools/xenstore/xenstored_core.c index 40fc8a7942..c91021876b 100644 --- a/tools/xenstore/xenstored_core.c +++ b/tools/xenstore/xenstored_core.c @@ -1540,10 +1540,49 @@ static void setup_structure(void) xs_daemon_transactions()); } +static void write_pidfile(const char *pidfile) +{ + char buf[100]; + int len; + int fd; + + fd = open(pidfile, O_RDWR | O_CREAT, 0600); + if (fd == -1) + barf_perror("Opening pid file %s", pidfile); + + /* We exit silently if daemon already running. */ + if (lockf(fd, F_TLOCK, 0) == -1) + exit(0); + + len = sprintf(buf, "%d\n", getpid()); + write(fd, buf, len); +} + +/* Stevens. */ +static void daemonize(void) +{ + pid_t pid; + + /* Separate from our parent via fork, so init inherits us. */ + if ((pid = fork()) < 0) + barf_perror("Failed to fork daemon"); + if (pid != 0) + exit(0); + + /* Session leader so ^C doesn't whack us. */ + setsid(); + /* Move off any mount points we might be in. */ + chdir("/"); + /* Discard our parent's old-fashioned umask prejudices. */ + umask(0); +} + + static struct option options[] = { { "no-fork", 0, NULL, 'N' }, { "verbose", 0, NULL, 'V' }, { "output-pid", 0, NULL, 'P' }, { "trace-file", 1, NULL, 'T' }, + { "pid-file", 1, NULL, 'F' }, { NULL, 0, NULL, 0 } }; int main(int argc, char *argv[]) @@ -1553,6 +1592,7 @@ int main(int argc, char *argv[]) fd_set inset, outset; bool dofork = true; bool outputpid = false; + const char *pidfile = NULL; while ((opt = getopt_long(argc, argv, "DVT:", options, NULL)) != -1) { switch (opt) { @@ -1572,11 +1612,20 @@ int main(int argc, char *argv[]) optarg); write(tracefd, "\n***\n", strlen("\n***\n")); break; + case 'F': + pidfile = optarg; } } if (optind != argc) barf("%s: No arguments desired", argv[0]); + if (dofork) { + openlog("xenstored", 0, LOG_DAEMON); + daemonize(); + } + if (pidfile) + write_pidfile(pidfile); + talloc_enable_leak_report_full(); /* Create sockets for them to listen to. */ @@ -1623,19 +1672,18 @@ int main(int argc, char *argv[]) /* Restore existing connections. */ restore_existing_connections(); - /* Debugging: daemonize() closes standard fds, so dup here. */ - tmpout = dup(STDOUT_FILENO); - if (dofork) { - openlog("xenstored", 0, LOG_DAEMON); - daemonize(); - } - if (outputpid) { char buffer[20]; sprintf(buffer, "%i\n", getpid()); write(tmpout, buffer, strlen(buffer)); } - close(tmpout); + + /* close stdin/stdout now we're ready to accept connections */ + if (dofork) { + close(STDIN_FILENO); + close(STDOUT_FILENO); + close(STDERR_FILENO); + } #ifdef TESTING signal(SIGUSR1, stop_failtest); -- 2.30.2